package com.hliushi.spark.rdd

import org.apache.spark.rdd.RDD
import org.junit.Test

/**
 * descriptions:
 *
 * author: Hliushi
 * date: 2021/5/16 20:28
 */
class Closure {


  val field = "hello "


  /**
   *
   * @param rdd
   * @return
   */
  def doStuff(rdd: RDD[String]): RDD[String] = {
    // 引用了Closure对象中的一个成员变量, 说明其可以访问Closure这个类的作用域
    // map中传入的是另一个匿名函数[x => filed + x], 传入这个函数就是一个闭包[它可以访问到非局部变量]
    // 这个闭包会被序列化运行在不同的Executor中
    rdd.map(x => field + x)
  }

  /**
   * 编写一个高阶函数, 在这个函数内要有一个变量, 返回是一个函数, 通过这个变量完成一个计算
   */
  @Test
  def test(): Unit = {
    //val f = closure()
    //val area = f(5)
    //println(s"area = ${area}")


    // 在这能是否访问到factor , 不能
    // 说明factor在一个单独的作用域中

    // 在拿到f的时候, 可以通过f间接的访问到closure作用域中的内容
    // 说明f携带一个作用域
    // 如果一个函数携带了一个外包的作用域, 这种函数我们称之为叫做闭包
    val f = closure()
    f(5)

    // 闭包的本质是什么?
    // f就是闭包, 闭包的本质就是一个函数
    // 在Scala中函数是一个特殊的类型, FunctionX
    // 闭包也是一个FunctionX类型的对象
    // 闭包是一个对象
  }


  /**
   * 返回一个新的函数
   *
   * @return Int => Double 返回是一个函数类型[在scala中函数一等公民]
   *         函数的输入参数为 Int, 输出参数为Double
   */
  def closure(): Int => Double = {
    val factor = 3.14
    val areaFunction: Int => Double = (r: Int) => {
      math.pow(r, 2) * factor
    }
    areaFunction
  }
}